// Kony

#pragma once

#include "CoreMinimal.h"
#include "GameplayTagContainer.h"
#include "GameFramework/SaveGame.h"
#include "LoadScreenSaveGame.generated.h"

class UGameplayAbility;
//保存插槽状态
UENUM(BlueprintType)
enum ESaveSlotStatus
{
	Vacant, //空的插槽
	EnterName, //输入昵称，创建插槽
	Taken //已占用，拥有存档
};
//保存能力信息 结构体
USTRUCT(BlueprintType)
struct FSavedAbility
{
	GENERATED_BODY()
	//游戏能力
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "ClassDefaultsAbility")
	TSubclassOf<UGameplayAbility> GameplayAbility;
	//能力标签
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	FGameplayTag AbilityTag = FGameplayTag();
	//能力状态标签
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	FGameplayTag AbilityStatusTag = FGameplayTag();
	//能力输入槽位标签
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	FGameplayTag AbilityInputTag = FGameplayTag();
	//能力类型标签
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	FGameplayTag AbilityTypeTag = FGameplayTag();
	//能力等级
	UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
	int32 AbilityLevel;
};
//判断能力标签匹配 用于在保存存档 存储能力时 使用AddUnique判断能力是否被添加过，避免重复添加（不添加这个判断 AddUnique 会编译报错）
inline bool operator==(const FSavedAbility& Left, const FSavedAbility& Right)
{
	return Left.AbilityTag.MatchesTagExact(Right.AbilityTag);
}
//保存的Actor结构体（用来保存世界中所有的需要存储的Actor）
USTRUCT()
struct FSavedActor
{
	GENERATED_BODY()
	//Actor 名称
	UPROPERTY()
	FString ActorName = FString();
	//Actor 位置旋转
	UPROPERTY()
	FTransform Transform = FTransform();
	//Serialized variables form the Actor - only those marked with SaveGame specifier
	//序列化的变量 - 只有标记了 SaveGame 的变量才会被保存这个变量
	UPROPERTY()
	TArray<uint8> Bytes;
	
};
//Actor 的 比较函数用于AddUnique 唯一性
inline bool operator==(const FSavedActor& Left, const FSavedActor& Right)
{
	return Left.ActorName == Right.ActorName;
}

//保存地图结构体
USTRUCT()
struct FSavedMap
{
	GENERATED_BODY()
	//地图名称 - 地图静态文件名称
	UPROPERTY()
	FString MapAssetName = FString();
	//地图内所有Actor数组
	UPROPERTY()
	TArray<FSavedActor> SavedActors;
};

/**
 * 加载场景保存游戏类 ， 这个类是UE的保存游戏数据的类 用于把插槽的数据通过这个 保存到游戏实例化对象
 */
UCLASS()
class GASC_HUANLING_API ULoadScreenSaveGame : public USaveGame
{
	GENERATED_BODY()
public:
	//槽位名称
	UPROPERTY()
	FString SlotName = FString();
	//槽位索引
	UPROPERTY()
	int32 SlotIndex = 0;
	//玩家名称
	UPROPERTY()
	FString PlayerName = FString("Default Name");
	//地图名称
	UPROPERTY()
	FString MapName = FString("Default Map Name");
	//地图资源名称
	UPROPERTY()
	FString MapAssetName = FString("Default Map Asset Name");
	//玩家开始位置标签，用于存储玩家最后一次存档所在位置
	UPROPERTY()
	FName PlayerStartTag;
	//插槽状态
	UPROPERTY()
	TEnumAsByte<ESaveSlotStatus> SaveSlotStatus = ESaveSlotStatus::Vacant;

	/* Player 玩家*/
	//玩家等级
	UPROPERTY()
	int32 PlayerLevel = 1;
	//玩家经验
	UPROPERTY()
	int32 XP = 0;
	//玩家灵气
	UPROPERTY()
	int32 LingQi = 0;
	//玩家技能点
	UPROPERTY()
	int32 SpellPoints = 0;
	//玩家属性点
	UPROPERTY()
	int32 AttributePoints = 0;

	//是否初次加载 - 用于区分主属性的加载方式（新建的角色是true ，之后保存角色后就变为false 读取数据就会改变读取数据资产方式）
	UPROPERTY()
	bool bFirstTimeLoadIn = true;
	
	/* 主属性 Primary Attributes */ 
	// 力量 Strength
	UPROPERTY()
	float Strength = 0.0f;
	// 智力 Intelligence
	UPROPERTY()
	float Intelligence = 0.0f;
	// 魂力 SoulPower
	UPROPERTY()
	float SoulPower = 0.0f;
	// 经脉 Resilience
	UPROPERTY()
	float Resilience = 0.0f;
	// 体魄 Vigor
	UPROPERTY()
	float Vigor = 0.0f;
	// 神识 Spirit
	UPROPERTY()
	float Spirit = 0.0f;
	// 身法 Agility
	UPROPERTY()
	float Agility = 0.0f;
	// 心境感悟 Insight
	UPROPERTY()
	float Insight = 0.0f;

	/* 能力 Abilities , 也就是玩家的各种技能*/
	UPROPERTY()
	TArray<FSavedAbility> SavedAbilities;
	/* 保存地图数据 保存去过的所有地图和其中的所有需要存储的Actor（存储世界变化就用这个） */
	UPROPERTY()
	TArray<FSavedMap> SavedMaps;
	//通过地图名获取存储的地图数据
	FSavedMap GetSavedMapWithMapName(const FString& InMapName);
	//判断是有对应地图
	bool HasMap(const FString& InMapName);
	

	
};
